﻿using System;
using System.Collections.Generic;
using Assist;
using Autodesk.Revit.DB;
using Autodesk.Revit.UI;
using YArchitech.Revit;
using YArchitech.Revit.RevitExtension;
using YJKExcelFormTool.Utilities;

namespace YJKExcelFormTool.Kits
{
	public class DrawLegendKit
	{
		public BoundingBoxUV BoundingBox
		{
			get
			{
				return this.m_BoundingBox;
			}
		}

		public DrawLegendKit(ExternalCommandData cmdData, FamilySymbol symbol, DrawLegendKit.ViewSectionType viewSectionType, ViewDetailLevel detailLevel, XYZ position)
		{
			this.m_Revit = cmdData;
			this.m_FamilySymbol = symbol;
			this.m_ViewDetailLevel = detailLevel;
			this.m_Position = position;
			this.m_ViewSectionType = viewSectionType;
			switch (viewSectionType)
			{
			case DrawLegendKit.ViewSectionType.VST_Front:
				this.m_ViewSectionNormal = -XYZ.BasisY;
				this.m_Transform = RevitVersionFuncs.CreateRotationAtPoint(-XYZ.BasisX, Math.PI*.5, new XYZ(0.0, 0.0, 0.0));
				return;
			case DrawLegendKit.ViewSectionType.VST_Back:
				this.m_ViewSectionNormal = XYZ.BasisY;
				this.m_Transform = RevitVersionFuncs.CreateRotationAtPoint(-XYZ.BasisX, Math.PI*.5, new XYZ(0.0, 0.0, 0.0));
				this.m_Transform *= RevitVersionFuncs.CreateRotationAtPoint(XYZ.BasisZ, Math.PI, new XYZ(0.0, 0.0, 0.0));
				return;
			case DrawLegendKit.ViewSectionType.VST_Left:
				this.m_ViewSectionNormal = -XYZ.BasisX;
				this.m_Transform = RevitVersionFuncs.CreateRotationAtPoint(-XYZ.BasisX, Math.PI*.5, new XYZ(0.0, 0.0, 0.0));
				this.m_Transform *= RevitVersionFuncs.CreateRotationAtPoint(XYZ.BasisZ, Math.PI*.5, new XYZ(0.0, 0.0, 0.0));
				return;
			case DrawLegendKit.ViewSectionType.VST_Right:
				this.m_ViewSectionNormal = XYZ.BasisX;
				this.m_Transform = RevitVersionFuncs.CreateRotationAtPoint(-XYZ.BasisX, Math.PI*.5, new XYZ(0.0, 0.0, 0.0));
				this.m_Transform *= RevitVersionFuncs.CreateRotationAtPoint(-XYZ.BasisZ, Math.PI*.5, new XYZ(0.0, 0.0, 0.0));
				return;
			case DrawLegendKit.ViewSectionType.VST_Top:
				this.m_ViewSectionNormal = XYZ.BasisZ;
				this.m_Transform = Transform.Identity;
				return;
			case DrawLegendKit.ViewSectionType.VST_Bottom:
				this.m_ViewSectionNormal = -XYZ.BasisZ;
				this.m_Transform = RevitVersionFuncs.CreateRotationAtPoint(XYZ.BasisY, Math.PI, new XYZ(0.0, 0.0, 0.0));
				this.m_Transform *= RevitVersionFuncs.CreateRotationAtPoint(XYZ.BasisZ, Math.PI, new XYZ(0.0, 0.0, 0.0));
				return;
			default:
				return;
			}
		}

		public Result GetLegendEdgeLoopList(double scale, bool drawName, bool drawDimention, ref List<List<List<Curve>>> edgeLoopList)
		{
			this.m_DrawName = drawName;
			this.m_DrawDimention = drawDimention;
			this.m_Transform = this.m_Transform.ScaleBasis(scale);
			this.GetLegendEdgeLoopList(ref edgeLoopList);
			return Autodesk.Revit.UI.Result.Succeeded;
		}

		public static Result DrawFilledRegionAndCreateGroup(ExternalCommandData cmdData, ElementId filledRegionTypeId, List<List<List<Curve>>> edgeLoopList, XYZ offset, string groupName, ref ElementId groupId)
		{
			Transform transform = RevitVersionFuncs.CreateTranslation(new XYZ(offset.X, offset.Y, 0.0));
			ElementSet elementSet = new ElementSet();
			foreach (List<List<Curve>> list in edgeLoopList)
			{
				List<CurveLoop> list2 = new List<CurveLoop>();
				foreach (List<Curve> list3 in list)
				{
					CurveLoop curveLoop = new CurveLoop();
					bool flag = true;
					foreach (Curve curve in list3)
					{
						Curve curve2 = RevitVersionFuncs.CreateTransformed(transform, curve);
						try
						{
							curveLoop.Append(curve2);
						}
						catch (Exception)
						{
							flag = false;
							break;
						}
					}
					if (flag)
					{
						list2.Add(curveLoop);
					}
				}
				try
				{
					FilledRegion filledRegion = FilledRegion.Create(cmdData.Application.ActiveUIDocument.Document, filledRegionTypeId, cmdData.Application.ActiveUIDocument.ActiveView.Id, list2);
					elementSet.Insert(filledRegion);
				}
				catch (Exception ex)
				{
					string message = ex.Message;
				}
			}
			try
			{
				Group group = null;
				if (elementSet.Size > 0)
				{
					group = RevitVersionFuncs.NewGroup(cmdData.Application.ActiveUIDocument.Document, elementSet);
				}
				if (group != null)
				{
					try
					{
						group.Name = groupName;
					}
					catch (Exception)
					{
					}
					groupId = group.Id;
				}
			}
			catch (Exception ex2)
			{
				string message2 = ex2.Message;
				return Autodesk.Revit.UI.Result.Failed;
			}
			return Autodesk.Revit.UI.Result.Succeeded;
		}

		private void GetLegendEdgeLoopList(ref List<List<List<Curve>>> faceEdgeLoopList)
		{
			foreach (Face face in this.GetFaceWithFamilyInstance())
			{
				List<List<Curve>> list;
				if (face.GetType() == typeof(PlanarFace))
				{
					XYZ normalWithFace = this.GetNormalWithFace(face);
					if (Geometry.IsParallel(normalWithFace, this.m_ViewSectionNormal))
					{
						list = this.GetEdgeLoopListByPositivePlane(face);
					}
					else
					{
						if (!Geometry.LessThan(normalWithFace.AngleTo(this.m_ViewSectionNormal), Math.PI*.5))
						{
							continue;
						}
						list = this.GetEdgeLoopListByInclinedPlane(face);
					}
				}
				else
				{
					list = this.GetEdgeLoopListByInclinedPlane(face);
				}
				List<List<Curve>> list2 = new List<List<Curve>>();
				foreach (List<Curve> curveList in list)
				{
					LoopSearcher loopSearcher = new LoopSearcher(this.m_Revit, true);
					try
					{
						List<List<Curve>> edgeLoopsByEdgeList = loopSearcher.GetEdgeLoopsByEdgeList(curveList);
						list2.AddRange(edgeLoopsByEdgeList);
					}
					catch (Exception ex)
					{
						string message = ex.Message;
					}
				}
				faceEdgeLoopList.Add(list2);
			}
		}

		private List<Face> GetFaceWithFamilyInstance()
		{
			List<Face> list = new List<Face>();
			Options options = new Options();
			options.ComputeReferences = true;
			options.DetailLevel = this.m_ViewDetailLevel;
			GeometryElement geometryElement = this.m_FamilySymbol.get_Geometry(options);
			if (geometryElement == null)
			{
				return list;
			}
			foreach (GeometryObject geometryObject in RevitVersionFuncs.GetGeometryObjectArray(geometryElement))
			{
				Solid solid = geometryObject as Solid;
				if (!(solid == null))
				{
					foreach (object obj in solid.Faces)
					{
						Face face = (Face)obj;
						if (face.GetType() == typeof(PlanarFace))
						{
							if (!Geometry.IsVertical(this.GetNormalWithFace(face), this.m_ViewSectionNormal))
							{
								list.Add(face);
							}
						}
						else
						{
							list.Add(face);
						}
					}
				}
			}
			list.Sort((Face face1, Face face2) => -FacePositionComparer.Compare(face1, face2, this.m_ViewSectionType));
			return list;
		}

		private static void FilterOverlapCurves(ref List<Curve> curveList, Curve addCurve)
		{
			int i = 0;
			if (addCurve.GetType() == typeof(Line))
			{
				Line item = addCurve as Line;
				while (i < curveList.Count)
				{
					Curve curve = curveList[i];
					if (!(curve.GetType() != typeof(Line)) && DrawLegendKit.Merge2Line(curve as Line, ref item))
					{
						curveList.RemoveAt(i);
						i--;
					}
					i++;
				}
				curveList.Add(item);
				return;
			}
			if (addCurve.GetType() == typeof(Arc))
			{
				Arc item2 = addCurve as Arc;
				while (i < curveList.Count)
				{
					Curve curve2 = curveList[i];
					if (!(curve2.GetType() != typeof(Arc)) && DrawLegendKit.Merge2Arc(curve2 as Arc, ref item2))
					{
						curveList.RemoveAt(i);
						i--;
					}
					i++;
				}
				curveList.Add(item2);
			}
		}

		private static bool Merge2Line(Line line1, ref Line line2)
		{
			XYZ hyendPoint = line1.GetEndPoint(0);
			XYZ hyendPoint2 = line1.GetEndPoint(1);
			XYZ a = hyendPoint2 - hyendPoint;
			XYZ hyendPoint3 = line2.GetEndPoint(0);
			XYZ hyendPoint4 = line2.GetEndPoint(1);
			XYZ b = hyendPoint4 - hyendPoint3;
			if (!Geometry.IsParallel(a, b))
			{
				return false;
			}
			bool flag = Geometry.Is_Point_OnSegment(hyendPoint3, hyendPoint4, hyendPoint);
			bool flag2 = Geometry.Is_Point_OnSegment(hyendPoint3, hyendPoint4, hyendPoint2);
			if (!flag && !flag2)
			{
				return false;
			}
			bool flag3 = Geometry.Is_Point_OnSegment(hyendPoint, hyendPoint2, hyendPoint3);
			bool flag4 = Geometry.Is_Point_OnSegment(hyendPoint, hyendPoint2, hyendPoint4);
			if (!flag3 && !flag4)
			{
				return false;
			}
			XYZ startPoint = null;
			XYZ endPoint = null;
			if (flag && flag2)
			{
				startPoint = hyendPoint3;
				endPoint = hyendPoint4;
			}
			else if (flag3 && flag4)
			{
				startPoint = hyendPoint;
				endPoint = hyendPoint2;
			}
			else if (flag && flag3)
			{
				startPoint = hyendPoint2;
				endPoint = hyendPoint4;
			}
			else if (flag && flag4)
			{
				startPoint = hyendPoint2;
				endPoint = hyendPoint3;
			}
			else if (flag2 && flag3)
			{
				startPoint = hyendPoint;
				endPoint = hyendPoint4;
			}
			else if (flag2 && flag4)
			{
				startPoint = hyendPoint;
				endPoint = hyendPoint3;
			}
			line2 = YJKLineEx.YJKGetBound(startPoint, endPoint);
			return true;
		}

		private static bool Merge2Arc(Arc arc1, ref Arc arc2)
		{
			return false;
		}

		private XYZ GetNormalWithFace(Face face)
		{
            UV uv = face.EdgeLoops.get_Item(0).get_Item(0).EvaluateOnFace(0.5, face);
			return face.ComputeNormal(uv);
		}

		private List<Line> GetLinesFromPoints(IList<XYZ> ptList)
		{
			List<Line> list = new List<Line>();
			if (ptList.Count < 2)
			{
				return list;
			}
			try
			{
				for (int i = 0; i < ptList.Count; i++)
				{
					ptList[i] = Geometry.TransformPoint(ptList[i], this.m_Transform);
				}
				for (int i = 1; i < ptList.Count; i++)
				{
					XYZ ptStart = ptList[i - 1];
					XYZ ptEnd = ptList[i];
					Line line = this.TranslateLine(ptStart, ptEnd);
					if (!(null == line))
					{
						list.Add(line);
					}
				}
			}
			catch (Exception ex)
			{
				string message = ex.Message;
				return list;
			}
			return list;
		}

		private List<Line> TessellateCurve(Curve curve)
		{
			IList<XYZ> ptList = curve.Tessellate();
			return this.GetLinesFromPoints(ptList);
		}

		private List<Line> TessellateCurveByInclinedPlane(Curve curve)
		{
			IList<XYZ> list = new List<XYZ>();
			try
			{
				list = curve.Tessellate();
			}
			catch (Exception)
			{
				return new List<Line>();
			}
			if (list == null)
			{
				return new List<Line>();
			}
			IList<XYZ> list2 = new List<XYZ>();
			for (int i = 0; i < list.Count; i++)
			{
				if (list[i] != null)
				{
					XYZ projectivePoint = this.GetProjectivePoint(list[i]);
					if (projectivePoint != null)
					{
						list2.Add(projectivePoint);
					}
				}
			}
			return this.GetLinesFromPoints(list2);
		}

		private Arc TranslateArc(Arc arc)
		{
			XYZ xyz = arc.GetEndPoint(0);
			XYZ xyz2 = arc.GetEndPoint(1);
			XYZ xyz3 = arc.Center;
			XYZ xyz4 = arc.Normal;
			xyz = Geometry.TransformPoint(xyz, this.m_Transform);
			xyz2 = Geometry.TransformPoint(xyz2, this.m_Transform);
			xyz3 = Geometry.TransformPoint(xyz3, this.m_Transform);
			xyz4 = Geometry.TransformPoint(xyz4, this.m_Transform);
			XYZ radianPnt = Geometry.CalculatMidPoint(xyz, xyz2, xyz3, xyz4);
			if (Geometry.Lessthan_Or_Equal((xyz2 - xyz).GetLength(), AssistFunc.mmToFeet(1.0)))
			{
				return null;
			}
			Arc arc2 = null;
			try
			{
				arc2 = this.m_Revit.Application.ActiveUIDocument.Document.CreatYJKArc(xyz, xyz2, radianPnt);
			}
			catch (Exception)
			{
				return null;
			}
			try
			{
				if (this.m_BoundingBox == null)
				{
					this.m_BoundingBox = Geometry.CalculateBoundingBox2D(arc2);
				}
				else
				{
					BoundingBoxUV boundingBoxUV = Geometry.CalculateBoundingBox2D(arc2);
					if (boundingBoxUV != null)
					{
						this.m_BoundingBox = Geometry.BoundingBoxesMerge(this.m_BoundingBox, boundingBoxUV);
					}
				}
			}
			catch (Exception)
			{
				return arc2;
			}
			return arc2;
		}

		private Line TranslateLine(XYZ ptStart, XYZ ptEnd)
		{
			if (Geometry.Lessthan_Or_Equal((ptEnd - ptStart).GetLength(), AssistFunc.mmToFeet(1.0)))
			{
				return null;
			}
			Line line = null;
			try
			{
				line = YJKLineEx.YJKGetBound(new XYZ(ptStart.X, ptStart.Y, 0.0), new XYZ(ptEnd.X, ptEnd.Y, 0.0));
			}
			catch (Exception)
			{
				return null;
			}
			try
			{
				if (this.m_BoundingBox == null)
				{
					this.m_BoundingBox = Geometry.CalculateBoundingBox2D(line);
				}
				else
				{
					BoundingBoxUV boundingBoxUV = Geometry.CalculateBoundingBox2D(line);
					if (boundingBoxUV != null)
					{
						this.m_BoundingBox = Geometry.BoundingBoxesMerge(this.m_BoundingBox, boundingBoxUV);
					}
				}
			}
			catch (Exception)
			{
				return line;
			}
			return line;
		}

		private Line TranslateLine(Line line)
		{
			XYZ xyz = line.GetEndPoint(0);
			XYZ xyz2 = line.GetEndPoint(1);
			xyz = Geometry.TransformPoint(xyz, this.m_Transform);
			xyz2 = Geometry.TransformPoint(xyz2, this.m_Transform);
			return this.TranslateLine(xyz, xyz2);
		}

		private Line TranslateHermiteSpline(HermiteSpline hermiteSpline)
		{
			XYZ xyz = hermiteSpline.GetEndPoint(0);
			XYZ xyz2 = hermiteSpline.GetEndPoint(1);
			xyz = Geometry.TransformPoint(xyz, this.m_Transform);
			xyz2 = Geometry.TransformPoint(xyz2, this.m_Transform);
			return this.TranslateLine(xyz, xyz2);
		}

		private Line TranslateLineByInclinedPlane(Line line)
		{
			XYZ xyz = this.GetProjectivePoint(line.GetEndPoint(0));
			XYZ xyz2 = this.GetProjectivePoint(line.GetEndPoint(1));
			xyz = Geometry.TransformPoint(xyz, this.m_Transform);
			xyz2 = Geometry.TransformPoint(xyz2, this.m_Transform);
			return this.TranslateLine(xyz, xyz2);
		}

		private XYZ GetProjectivePoint(XYZ pt)
		{
			XYZ result = null;
			try
			{
				if (!Geometry.IsEqual(this.m_ViewSectionNormal.X, 0.0))
				{
					result = new XYZ(0.0, pt.Y, pt.Z);
				}
				else if (!Geometry.IsEqual(this.m_ViewSectionNormal.Y, 0.0))
				{
					result = new XYZ(pt.X, 0.0, pt.Z);
				}
				else
				{
					result = new XYZ(pt.X, pt.Y, 0.0);
				}
			}
			catch (Exception ex)
			{
				string message = ex.Message;
				return result;
			}
			return result;
		}

		private List<List<Curve>> GetEdgeLoopListByPositivePlane(Face face)
		{
			List<List<Curve>> list = new List<List<Curve>>();
			foreach (object obj in face.EdgeLoops)
			{
				EdgeArray edgeArray = (EdgeArray)obj;
				List<Curve> list2 = new List<Curve>();
				foreach (object obj2 in edgeArray)
				{
					Curve curve = ((Edge)obj2).AsCurve();
					if (curve.GetType() == typeof(Line))
					{
						Line line = this.TranslateLine(curve as Line);
						if (null != line)
						{
							list2.Add(line);
						}
					}
					else if (curve.GetType() == typeof(Arc))
					{
						Arc arc = this.TranslateArc(curve as Arc);
						if (null != arc)
						{
							list2.Add(arc);
						}
					}
					else if (curve.GetType() == typeof(Ellipse))
					{
						List<Line> collection = this.TessellateCurve(curve);
						list2.AddRange(collection);
					}
					else if (curve.GetType() == typeof(HermiteSpline))
					{
						Line line2 = this.TranslateHermiteSpline(curve as HermiteSpline);
						if (null != line2)
						{
							list2.Add(line2);
						}
					}
				}
				list.Add(list2);
			}
			return list;
		}

		private List<List<Curve>> GetEdgeLoopListByInclinedPlane(Face face)
		{
			List<List<Curve>> list = new List<List<Curve>>();
			foreach (object obj in face.EdgeLoops)
			{
				EdgeArray edgeArray = (EdgeArray)obj;
				List<Curve> list2 = new List<Curve>();
				foreach (object obj2 in edgeArray)
				{
					Curve curve = ((Edge)obj2).AsCurve();
					if (curve.GetType() == typeof(Line))
					{
						Line line = this.TranslateLineByInclinedPlane(curve as Line);
						if (null != line)
						{
							list2.Add(line);
						}
					}
					else
					{
						List<Line> collection = this.TessellateCurveByInclinedPlane(curve);
						list2.AddRange(collection);
					}
				}
				list.Add(list2);
			}
			return list;
		}

		private ExternalCommandData m_Revit;

		private FamilySymbol m_FamilySymbol;

		private ViewDetailLevel m_ViewDetailLevel;

		private XYZ m_ViewSectionNormal;

		private Transform m_Transform;

		private XYZ m_Position;

		private BoundingBoxUV m_BoundingBox;

		private bool m_DrawName;

		private bool m_DrawDimention;

		private DrawLegendKit.ViewSectionType m_ViewSectionType;

		public enum ViewSectionType
		{
			VST_Front,
			VST_Back,
			VST_Left,
			VST_Right,
			VST_Top,
			VST_Bottom
		}
	}
}
